import { Injectable } from '@nestjs/common'
import { Workflow, WorkflowNode } from '../workflow.builder'

export class WorkflowValidationError extends Error {
    constructor(message: string, public details: any) {
        super(message)
        this.name = 'WorkflowValidationError'
    }
}

@Injectable()
export class WorkflowValidator {
    // 验证工作流结构
    validateWorkflow(workflow: Workflow): void {
        // 检查基本结构
        if (!workflow || typeof workflow !== 'object') {
            throw new WorkflowValidationError('Invalid workflow structure', { workflow })
        }

        if (!Array.isArray(workflow.nodes)) {
            throw new WorkflowValidationError('Workflow nodes must be an array', {
                nodes: workflow.nodes
            })
        }

        if (!Array.isArray(workflow.edges)) {
            throw new WorkflowValidationError('Workflow edges must be an array', {
                edges: workflow.edges
            })
        }

        // 验证节点
        workflow.nodes.forEach((node, index) => {
            this.validateNode(node, index)
        })

        // 验证边
        workflow.edges.forEach((edge, index) => {
            this.validateEdge(edge, index, workflow)
        })

        // 验证工作流完整性
        this.validateWorkflowCompleteness(workflow)
    }

    // 验证单个节点
    private validateNode(node: WorkflowNode, index: number): void {
        if (!node.id) {
            throw new WorkflowValidationError(`Node at index ${index} missing id`, { node })
        }

        if (!node.type) {
            throw new WorkflowValidationError(`Node ${node.id} missing type`, { node })
        }

        if (!node.class_type) {
            throw new WorkflowValidationError(`Node ${node.id} missing class_type`, { node })
        }

        if (!node.inputs || typeof node.inputs !== 'object') {
            throw new WorkflowValidationError(`Node ${node.id} has invalid inputs`, { node })
        }

        // 验证必需的输入参数
        this.validateNodeInputs(node)
    }

    // 验证节点输入
    private validateNodeInputs(node: WorkflowNode): void {
        const requiredInputs = this.getRequiredInputs(node.class_type)
        for (const input of requiredInputs) {
            if (!(input in node.inputs)) {
                throw new WorkflowValidationError(
                    `Node ${node.id} missing required input: ${input}`,
                    { node, requiredInput: input }
                )
            }
        }
    }

    // 验证边
    private validateEdge(edge: any, index: number, workflow: Workflow): void {
        if (!edge.from_node) {
            throw new WorkflowValidationError(`Edge at index ${index} missing from_node`, { edge })
        }

        if (!edge.to_node) {
            throw new WorkflowValidationError(`Edge at index ${index} missing to_node`, { edge })
        }

        if (!edge.from_output) {
            throw new WorkflowValidationError(`Edge at index ${index} missing from_output`, { edge })
        }

        if (!edge.to_input) {
            throw new WorkflowValidationError(`Edge at index ${index} missing to_input`, { edge })
        }

        // 验证节点存在性
        const fromNode = workflow.nodes.find(n => n.id === edge.from_node)
        const toNode = workflow.nodes.find(n => n.id === edge.to_node)

        if (!fromNode) {
            throw new WorkflowValidationError(
                `Edge references non-existent from_node: ${edge.from_node}`,
                { edge }
            )
        }

        if (!toNode) {
            throw new WorkflowValidationError(
                `Edge references non-existent to_node: ${edge.to_node}`,
                { edge }
            )
        }
    }

    // 验证工作流完整性
    private validateWorkflowCompleteness(workflow: Workflow): void {
        // 检查是否有孤立节点
        const connectedNodes = new Set<number>()
        workflow.edges.forEach(edge => {
            connectedNodes.add(edge.from_node)
            connectedNodes.add(edge.to_node)
        })

        const isolatedNodes = workflow.nodes
            .filter(node => !connectedNodes.has(node.id))
            .map(node => node.id)

        if (isolatedNodes.length > 0) {
            throw new WorkflowValidationError('Workflow contains isolated nodes', {
                isolatedNodes
            })
        }

        // 检查是否有循环依赖
        this.checkForCycles(workflow)
    }

    // 检查循环依赖
    private checkForCycles(workflow: Workflow): void {
        const visited = new Set<number>()
        const recursionStack = new Set<number>()

        const hasCycle = (nodeId: number): boolean => {
            if (recursionStack.has(nodeId)) {
                return true
            }

            if (visited.has(nodeId)) {
                return false
            }

            visited.add(nodeId)
            recursionStack.add(nodeId)

            const outgoingEdges = workflow.edges.filter(e => e.from_node === nodeId)
            for (const edge of outgoingEdges) {
                if (hasCycle(edge.to_node)) {
                    return true
                }
            }

            recursionStack.delete(nodeId)
            return false
        }

        for (const node of workflow.nodes) {
            if (hasCycle(node.id)) {
                throw new WorkflowValidationError('Workflow contains cycles', {
                    workflow
                })
            }
        }
    }

    // 获取节点类型的必需输入
    private getRequiredInputs(classType: string): string[] {
        // 这里可以根据不同的节点类型定义必需的输入
        const requiredInputsMap: Record<string, string[]> = {
            'CheckpointLoaderSimple': ['ckpt_name'],
            'CLIPTextEncode': ['text', 'clip'],
            'KSampler': ['model', 'positive', 'negative', 'latent_image'],
            'VAEDecode': ['samples', 'vae'],
            'SaveImage': ['images']
        }

        return requiredInputsMap[classType] || []
    }
} 